package com.myalibaba.example;

import java.util.concurrent.locks.ReentrantLock;

/**
 * ReentrantLock是一个非常有用的类，用于实现锁的功能，允许线程在等待锁时能够响应中断，并且可以通过尝试锁定而不阻塞线程。
 * 使用 ReentrantLock 可以确保多线程环境中对共享资源的安全访问。
 */
public class ReentrantLockExample {
    //ReentrantLock 对象被声明为类的一个成员变量，用于控制对共享资源的访问。
    private final ReentrantLock lock = new ReentrantLock();
    private int sharedCounter = 0;

    public void increment() {
        lock.lock();
        try {
            //使用 lock.lock() 来获取锁，确保当前线程独占对 sharedCounter 变量的访问权限。
            sharedCounter++;
            System.out.println(Thread.currentThread().getName() + " incremented counter to: " + sharedCounter);
        } finally {
            lock.unlock();
        }
    }

    //该方法用于安全地读取共享变量的值，同样使用 lock 机制保护。
    public int getSharedCounter() {
        lock.lock();
        try {
            return sharedCounter;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ReentrantLockExample example = new ReentrantLockExample();

        Runnable task = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    example.increment();
                }
            }
        };

        //创建并启动两个线程来执行该任务。
        Thread thread1 = new Thread(task, "Thread-1");
        Thread thread2 = new Thread(task, "Thread-2");

        thread1.start();
        thread2.start();

        try {
            /**
             * 使用 join 方法等待两个线程执行完毕。
             * 当一个线程调用另一个线程的 join 方法时，它会暂停执行，直到目标线程完成。
             * 主线程启动两个子线程 thread1 和 thread2，并等待它们完成。
             * 使用 join 方法确保主线程等待子线程终止，避免主线程在子线程完成之前结束。
             * 通过这种方式，可以确保多线程执行的顺序和正确性，主线程只有在所有子线程完成后才会继续执行。
             */
           thread1.join();
           thread2.join();
        } catch (Exception e) {
            e.printStackTrace();
        }

        //最后打印共享计数器的最终值。
        System.out.println("Final counter value: " + example.getSharedCounter());
    }
}
